﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;

namespace Jemgine.Engine.Scripts
{
    public class TemplatedEntityData : Jemgine.Engine.EntityComponent
    {
        internal TemplatedImport Creator = null;
    }

    [Jemgine.Engine.Node, Jemgine.Engine.Category("System")]
    public class TemplatedImport : Jemgine.Data.ScriptNode
    {
        [System.ComponentModel.Editor(typeof(Data.MapEditor), typeof(System.Drawing.Design.UITypeEditor))]
        public string TemplateName { get; set; }

        [ContentSerializer(Optional = true)]
        public int SpawnLimit { get; set; }

        private Data.MapData Template = null;
        private bool TriedLoad = false;
        private Data.EntityRecord Entity = null;
        private List<Data.EntityRecord> Recycled = new List<Data.EntityRecord>();
        private TemplatedEntityData EntityData = null;
        private int ActiveEntities = 0;

        private class TooManyEntitiesException : Exception {}

        private void ElementHandler(Data.MapElement Element)
        {
            if (!(Element is Data.ScriptNode)) throw new InvalidOperationException();
            if (this.Entity != null && Element is Data.EntityRecord) throw new TooManyEntitiesException();
            var Entity = Element as Data.EntityRecord;
            if (Entity != null) this.Entity = (Data.EntityRecord)Entity.Clone();
        }

        public TemplatedImport()
        {
            AddInput("Fire", null);
            AddOutput("Relay", null);

            SpawnLimit = -1;
        }

        private void TryLoad()
        {
            if (TriedLoad) return;
            TriedLoad = true;

            try
            {
                bool Success = Sim.ImportMap(out Template, TemplateName, Position, false, ElementHandler);
                EntityData = new TemplatedEntityData { Creator = this };
            }
            catch (TooManyEntitiesException) { Template = null; }
        }

        public override void FireTerminal(int InputID, Jemgine.Data.ScriptPayload Payload)
        {
            if (InputID == 0 && (SpawnLimit == -1 || ActiveEntities < SpawnLimit))
            {
                if (!TriedLoad) TryLoad();
                if (Template == null) return;

                Data.EntityRecord Entity = null;
                if (Recycled.Count > 0)
                {
                    Entity = Recycled[Recycled.Count - 1];
                    Recycled.RemoveAt(Recycled.Count - 1);

                    Entity.Reset(this.Entity);
                    Entity.state = Data.EntityRecord.State.PreCreated;
                }
                else
                {
                    Entity = this.Entity.Clone() as Data.EntityRecord;
        
                    for (int i = 0; i < Template.Elements.Count; ++i)
                    {
                        if (Template.Elements[i] is Data.EntityRecord)
                            Template.Elements[i] = Entity;
                    }

                    Template.EnumerateTargets();
                    Entity.PostProcess(Vector2.Zero, Template, Sim);
                    Sim.InitializePrecreatedEntity(Entity, false);
                    Entity.AttachedElements.Add(EntityData);
                }

                Sim.AddPrecreatedEntity(Entity);

                ActiveEntities += 1;
            }

            OutputTerminals[0].Fire(Payload);

        }

        internal void Recycle(Data.EntityRecord Entity)
        {
            Sim.RemovePrecreatedEntity(Entity);
            Recycled.Add(Entity);
            ActiveEntities -= 1;
        }
    }

    
}
